package com.tbi.graphcolouring.algorithmconfiguration.crosser;

import java.util.Arrays;
import java.util.List;

import com.tbi.algorithm.configuration.ICrosser;
import com.tbi.graphcolouring.AlgorithmSettings;
import com.tbi.graphcolouring.PopulationEntity;
import com.tbi.graphcolouring.utils.Random;

public class MultiPointCrosser implements ICrosser{

	@Override
	public void crossOver(List<Object> population) {
		int wholePopulationSize = AlgorithmSettings.POPULATION_SIZE;
		int numberOfCrossPoints = AlgorithmSettings.NUMBER_OF_CROSS_POINTS;
		int currentPopulationSize = population.size();
		
		while(currentPopulationSize <= wholePopulationSize){
//			PopulationEntity entity1 = (PopulationEntity) population.get((int)(Random.uniform(0,currentPopulationSize)));
//			PopulationEntity entity2 = (PopulationEntity) population.get((int)(Random.uniform(0,currentPopulationSize)));
			PopulationEntity entity1 = (PopulationEntity) population.get((int)(Random.scaledGaussian(currentPopulationSize)));
			PopulationEntity entity2 = (PopulationEntity) population.get((int)(Random.scaledGaussian(currentPopulationSize)));
			
			if(entity1 == entity2){
				continue;
			}
			
			int[] entity1ColorsCopy = Arrays.copyOf(entity1.colors, entity1.colors.length);
			int[] entity2ColorsCopy = Arrays.copyOf(entity2.colors, entity2.colors.length);
			
			if(AlgorithmSettings.RANDOMIZE_NUMBER_OF_CROSS_POINTS){
				numberOfCrossPoints = (int) Random.uniform(1, entity1.colors.length/2);
			}
			
			cross(entity1ColorsCopy, entity2ColorsCopy, numberOfCrossPoints);
			
			PopulationEntity newEntity1 = new PopulationEntity(0);
			newEntity1.colors = entity1ColorsCopy;
			PopulationEntity newEntity2 = new PopulationEntity(0);
			newEntity2.colors = entity2ColorsCopy;
			
			population.add(newEntity1);
			population.add(newEntity2);
			currentPopulationSize = currentPopulationSize+2;
		}
	}
	
	private void cross(int[] a, int[] b, int numberOfCrossPoints) {
		if(a.length != b.length){
			throw new IllegalArgumentException();
		}
		
		int gapBetweenCrossPoints = a.length / (numberOfCrossPoints+1);
		boolean swap = true; //first piece of chromosome does not swap. This flag changes on the beggining of loop.
		int crossPointCounter = -1; //first loop call increments this, so I set it to -1
		
		for (int i = 0; i < a.length; i++) {
			if(i%gapBetweenCrossPoints==0 && crossPointCounter != numberOfCrossPoints){
				swap = !swap;
				crossPointCounter++;
			}
			if(swap){
				if(Random.checkSuccess(AlgorithmSettings.CROSSOVER_PROBABILITY)){//normal swap
					int temp = a[i];
					a[i] = b[i];
					b[i] = temp;
				}
//				else{//reverse swap
//					int temp = a[i];
//					a[i] = b[b.length - i];
//					b[b.length - i] = temp;
//				}
			}
		}
	}
}
